import datetime

from  peewee import *
from sqlalchemy import Column, String, Integer, DateTime, func, Numeric

from database import db


class ProductContent(database.Model):
    language = CharField(db_column='language', max_length=10, null=False)
    product_id = CharField(db_column='product_id', null=False)
    summary = CharField(db_column='summary', max_length=400, help_text='产品摘要', null=True)
    detail = TextField(db_column='detail', help_text='产品详情')

    class Meta:
        # db_table = '{0}_{1}'.format(TABLE_PREFIX, 'product_content')
        primary_key = CompositeKey('language', 'product_id')


class ProductCategory(database.Model):
    id = CharField(db_column='id', max_length=40, primary_key=True)
    screen_name = CharField(db_column='screen_name', help_text='显示名称', null=False)

    # class Meta:
    #     db_table = '{0}_{1}'.format(TABLE_PREFIX, 'product_categories')


class Metadata(database.Model):
    id = CharField(db_column='id', max_length=40, primary_key=True)
    screen_name = CharField(db_column='screen_name', help_text='显示名称 ')
    product_category = ForeignKeyField(ProductCategory)
    value_mode = CharField(db_column='value_mode', help_text='设置值模式', default='text')
    extension = TextField(db_column='extension', help_text='扩展字段，根据设置值模式不同而不同', null=True)

    # product_metadata = ManyToManyField()
    # class Meta:
    #     db_table = '{0}_{1}'.format(TABLE_PREFIX, 'product_metas')


# ProductMetadataThroughModel = DeferredThroughModel()



class Product(db.Model):
    id = Column(String(200), primary_key=True)
    title = Column(String(400))
    sub_title = Column(String(400))
    status = Column(String(20), default='normal')
    created_at = Column(DateTime, default=func.now())
    updated_at = Column(DateTime, default=func.now())
    like_count = Column(Integer, default=0)
    view_count = Column(Integer, default=0)
    mask = Column(String(32), nullable=True)
    structure = Column(String(80), nullable=True)
    minimum_price = Column(Numeric(precision=4), default=0.00)
    maximum_price = Column(Numeric(precision=4), default=0.00)
    stock = Column(Integer, default=0)
    cover = Column(String(400))
    category = Column()


class Product(database.Model):
    def __init__(self):
        database.Model.__init__(self)
        self._metadata = None
        self._stock = None

    id = CharField(db_column="id", max_length=50, primary_key=True)
    title = CharField(db_column='title', max_length=255, help_text='产品名称', null=False)
    sub_title = CharField(db_column='sub_title', max_length=200, help_text='子名称', null=True)
    type = CharField(db_column='type', max_length=20, default='game', help_text='产品类型')
    status = CharField(db_column='status', max_length=20, default='normal', help_text='产品状态')
    created_at = DateTimeField(db_column='created_at', default=datetime.datetime.now, help_text='创建时间')
    updated_at = DateTimeField(db_column='updated_at', help_text='最后更新时间', null=True)
    cover = CharField(db_column='cover', help_text='产品封面图片地址', max_length=400, null=True)
    like_count = IntegerField(db_column='like_count', help_text='产品喜欢人数', default=0)
    click_count = IntegerField(db_column='click_count', help_text='产品被点击数', default=0)
    collection_count = IntegerField(db_column='collection_count', help_text='收蒧数目', default=0)
    mask = CharField(db_column='mask', help_text='掩码，扩展用', max_length=32, null=True)
    category = ForeignKeyField(ProductCategory, help_text='产品分类Id')
    structure = CharField(db_column='structure', help_text='产品目录结构', max_length=80, null=True)

    # metadata = ManyToManyField(Metadata, related_name='metadata', through_model=ProductMetadataThroughModel)


    # class Meta:
    #     db_table = '{0}_{1}'.format(TABLE_PREFIX, 'products')

    def get_content(self, language=None):
        query = ProductContent.select().where(ProductContent.product_id == self.id)
        if language:
            query = query.where(ProductContent.language == language)
        return query.execute()

    @classmethod
    def __with_meta(cls):
        return prefetch(ProductMetadata.select(), Metadata.select())

    @classmethod
    def __with_metadata(cls, *args, **kwargs
                        ):
        order_by = kwargs.pop('order_by', None)
        if order_by:
            query = Product.select().order_by(order_by)
        else:
            query = Product.select().order_by(Product.click_count.desc())
        limit = kwargs.pop('limit', None)
        page = kwargs.pop('offset', None)
        if limit:
            query = query.limit(limit)
        if page:
            query = query.offset((page - 1) * limit)

        for arg in args:
            query = query.where(arg)

        return prefetch(query, cls.__with_meta())

    @classmethod
    def get_list_count(cls, *args):
        query = Product.select()
        for condition in args:
            query = query.where(condition)
        return query.count()

    @classmethod
    def __set_metadata(cls, product):
        if hasattr(product, 'productmetadata_set_prefetch'):
            # setattr(product, 'metadata', getattr(product, 'productmetadata_set_prefetch'))
            product.metadata.append(getattr(product, 'productmetadata_set_prefetch'))
        return True

    @property
    def metadata(self):
        if not self._metadata:
            self._metadata = list(ProductMetadata.select().where(ProductMetadata.product == self))
        return self._metadata

    @property
    def stock(self):
        if not self._stock:
            from ..models.offer import Offer

            self._stock = list(Offer.select().where(Offer.product == self).execute())
        return self._stock

    @classmethod
    def __warp(cls, data_list):
        def _w(p):
            if hasattr(p, 'productmetadata_set_prefetch'):
                setattr(p, '_metadata', getattr(p, 'productmetadata_set_prefetch'))

            if hasattr(p, 'stock_set_prefetch'):
                setattr(p, '_stock', getattr(p, 'stock_set_prefetch'))
            return True

        return filter(lambda p: _w(p), data_list)

    @classmethod
    def get_list_with_stock(cls, *args, **kwargs):
        from .offer import Offer
        return cls.__warp(prefetch(cls.__with_metadata(*args, **kwargs), Offer.select()))

    @classmethod
    def get_list(cls, *args, **kwargs):
        return cls.__warp(cls.__with_metadata(*args, **kwargs))


class ProductMetadata(database.Model):
    product = ForeignKeyField(Product, db_column='product_id')
    metadata = ForeignKeyField(Metadata, db_column='metadata_id')
    value = CharField(db_column='value', help_text='元数据值', max_length=400)

    class Meta:
        # db_table = '{0}_{1}'.format(TABLE_PREFIX, 'product_metadata')
        primary_key = CompositeKey('product', 'metadata')
